#include "../main.h"

#define FILE_EXIST 1
#define FILE_NOT_EXIST 0
char *stop_tag_clientId = NULL;

void process_up_filehead(int sockfd, char *msg, char *clientId)
{
    cJSON *pRank = NULL, *pValue = NULL;
    pRank = cJSON_Parse(msg);
    if (pRank == NULL)
    {
        OUT_DEBUG(DEBUG, "json 解析异常");
        OUT_DEBUG(DEBUG, "msg:%s", msg);
    }
    else
    {
        char *file_name = NULL;
        int file_type = -1;
        int bContinue = 0;
        pValue = cJSON_GetObjectItem(pRank, "fileName");
        if (pValue != NULL && pValue->type == cJSON_String)
        {
            int length = strlen(pValue->valuestring);
            file_name = charCopy(pValue->valuestring, length + 1);
            file_name[length] = '\0';
        }
        pValue = cJSON_GetObjectItem(pRank, "fileType");
        if (pValue != NULL && pValue->type == cJSON_Number)
        {
            file_type = pValue->valueint;
        }
        pValue = cJSON_GetObjectItem(pRank, "offset");
        if (pValue != NULL && pValue->type == cJSON_Number)
        {
            int offset = pValue->valueint;
            if (offset > 0)
            {
                OUT_DEBUG(DEBUG, "file %s offset>0  but not continue", file_name);
            }
        }
        pValue = cJSON_GetObjectItem(pRank, "bContinue");
        if (pValue != NULL && pValue->type == cJSON_Number)
        {
            int bContinue = pValue->valueint;
            if (bContinue > 0)
            {
                OUT_DEBUG(DEBUG, "file %s offset>0  and is continue", file_name);
            }
        }
        long total_size = 0;
        pValue = cJSON_GetObjectItem(pRank, "total");
        if (pValue != NULL && pValue->type == cJSON_Number)
        {
            total_size = pValue->valueint;
            int can_upload = check_has_disk(total_size);
            if (can_upload == 1)
            {
                char *file_path = create_dist_file(file_type, file_name);
                if (file_path != NULL)
                {
                    int ret = createfile(file_path);
                    if (ret == 1)
                    {
                        OUT_DEBUG(DEBUG, "create %s file  success", file_name);
                    }
                    else
                    {
                        OUT_DEBUG(DEBUG, "create %s file error", file_name);
                    }
                }
                char msg[100] = "文件创建成功";
                reply_up_filehead(sockfd, file_path, msg, clientId, 1);
                free(file_path);
                file_path = NULL;
            }
            else
            {
                // char  = "文件创建成功";
                char msg[100] = "磁盘空间不足";
                reply_up_filehead(sockfd, NULL, msg, clientId, 0);
            }
        }
        if (file_name != NULL)
        {
            free(file_name);
            file_name = NULL;
        }
        cJSON_Delete(pRank);
    }
}

void reply_up_filehead(int sockfd, char *file_path, char *msg, char *clientId, int result_code)
{
    char data[1024];
    cJSON *down_check = NULL;
    cJSON *result_info = NULL;

    result_info = cJSON_CreateObject();
    cJSON_AddBoolToObject(result_info, "bResult", 1);
    cJSON_AddNumberToObject(result_info, "resultCode", result_code);
    cJSON_AddStringToObject(result_info, "resultMsg", msg);
    if (file_path != NULL)
    {
        long current_size = get_file_totalSize(file_path);
        OUT_DEBUG(DEBUG, "filepath:%s,filesize:%d", file_path, current_size);
        cJSON_AddNumberToObject(result_info, "currentSize", current_size);
    }

    down_check = cJSON_CreateObject();
    cJSON_AddStringToObject(down_check, "type", "DEVICE_FILE_UPLOAD_CHECK");
    cJSON_AddStringToObject(down_check, "clientId", get_routerid());
    cJSON_AddStringToObject(down_check, "content", cJSON_PrintUnformatted(result_info));

    if (clientId != NULL)
    {
        cJSON_AddStringToObject(down_check, "tagClientId", clientId);
    }

    char *buffer = cJSON_PrintUnformatted(down_check);
    int msg_size = strlen(buffer);
    memset(data, 0, sizeof(data));
    memcpy(data, buffer, msg_size);

    if (result_info != NULL)
    {
        cJSON_Delete(result_info);
    }
    if (down_check != NULL)
    {
        cJSON_Delete(down_check);
    }
    OUT_DEBUG(DEBUG, "return_data: %s ", data);
    encode_msg(sockfd, data, msg_size);

    if (buffer != NULL)
    {
        free(buffer);
        buffer = NULL;
    }
}

void process_up_file(int sockfd, char *clientId, char *msg, char *data)
{
    cJSON *pRank = NULL, *pValue = NULL;
    pRank = cJSON_Parse(msg);
    int file_type = -1;
    if (pRank == NULL)
    {
        OUT_DEBUG(DEBUG, "json 解析异常");
        OUT_DEBUG(DEBUG, "msg:%s", msg);
    }
    else
    {
        FileInfo *fileInfo = create_file_info();
        pValue = cJSON_GetObjectItem(pRank, "fileName");
        if (pValue != NULL && pValue->type == cJSON_String)
        {
            int length = strlen(pValue->valuestring);
            fileInfo->fileName = charCopy(pValue->valuestring, length + 1);
            fileInfo->fileName[length] = '\0';
        }
        pValue = cJSON_GetObjectItem(pRank, "offset");
        if (pValue != NULL && pValue->type == cJSON_Number)
        {
            fileInfo->currentIndex = pValue->valueint;
        }
        pValue = cJSON_GetObjectItem(pRank, "total");
        if (pValue != NULL && pValue->type == cJSON_Number)
        {
            fileInfo->totalsize = pValue->valueint;
        }
        pValue = cJSON_GetObjectItem(pRank, "size");
        if (pValue != NULL && pValue->type == cJSON_Number)
        {
            fileInfo->size = pValue->valueint;
        }
        pValue = cJSON_GetObjectItem(pRank, "mValue");
        if (pValue != NULL && pValue->type == cJSON_String)
        {
            int length = strlen(pValue->valuestring);
            fileInfo->md5_value = charCopy(pValue->valuestring, length + 1);
            fileInfo->md5_value[length] = '\0';
        }
        pValue = cJSON_GetObjectItem(pRank, "fileType");
        if (pValue != NULL && pValue->type == cJSON_Number)
        {
            file_type = pValue->valueint;
        }
        char *file_path = create_dist_file(file_type, fileInfo->fileName);
        if (file_path != NULL)
        {
            int ret = createfile(file_path);
            if (ret == 1)
            {
                fileInfo->bytes = (char *)malloc(fileInfo->size);
                memset(fileInfo->bytes, 0, fileInfo->size);
                memcpy(fileInfo->bytes, data, fileInfo->size);
                writeFileInfo(fileInfo, file_path);
                if (fileInfo->bytes)
                {
                    free(fileInfo->bytes);
                    fileInfo->bytes = NULL;
                }
            }
            if (fileInfo->totalsize <= fileInfo->size + fileInfo->currentIndex)
            {
                reply_upfile_end(sockfd, clientId, fileInfo->fileName);
                if (file_type == 1)
                {
                    post_img_file(file_path, fileInfo->fileName);
                }
            }
            free(file_path);
            file_path = NULL;
        }
        cJSON_Delete(pRank);
        freeFileInfo(fileInfo);
    }
}

//回复文件发送完成时，需要压缩图片
void reply_upfile_end(int sockfd, char *clientId, char *file_name)
{
    //int ret = 0;
    char data[1024];
    cJSON *down_resp = NULL;
    cJSON *result_info = NULL;

    result_info = cJSON_CreateObject();
    cJSON_AddStringToObject(result_info, "fileName", file_name);
    cJSON_AddBoolToObject(result_info, "bResult", 1);
    cJSON_AddNumberToObject(result_info, "resultCode", 1);
    cJSON_AddStringToObject(result_info, "resultMsg", "");

    down_resp = cJSON_CreateObject();
    cJSON_AddStringToObject(down_resp, "type", "DEVICE_FILE_UPLOAD_RSP");
    cJSON_AddStringToObject(down_resp, "clientId", get_routerid());
    cJSON_AddStringToObject(down_resp, "content", cJSON_PrintUnformatted(result_info));

    if (clientId != NULL)
    {
        cJSON_AddStringToObject(down_resp, "tagClientId", clientId);
    }

    char *buffer = cJSON_PrintUnformatted(down_resp);
    int msg_size = strlen(buffer);
    memset(data, 0, sizeof(data));
    memcpy(data, buffer, msg_size);
    if (result_info != NULL)
    {
        cJSON_Delete(result_info);
    }
    if (down_resp != NULL)
    {
        cJSON_Delete(down_resp);
    }
    encode_msg(sockfd, data, msg_size);
}

//处理下载头信息
void process_down_head(int sockfd, char *clientId, char *msg)
{
    cJSON *pRank = NULL, *pValue = NULL;
    pRank = cJSON_Parse(msg);
    if (pRank == NULL)
    {
        OUT_DEBUG(DEBUG, "json 解析异常");
        printf("msg:%s", msg);
    }
    else
    {
        pValue = cJSON_GetObjectItem(pRank, "filePath");
        if (pValue != NULL && pValue->type == cJSON_String)
        {
            int length = strlen(pValue->valuestring);
            char *file_path = charCopy(pValue->valuestring, length + 1);
            if (isExist(file_path) == 1)
            {
                OUT_DEBUG(DEBUG, "file is exit path:%s", file_path);
                long totalSize = get_file_totalSize(file_path);
                send_down_filehead(sockfd, clientId, file_path, totalSize, FILE_EXIST);
            }
            else
            {
                OUT_DEBUG(DEBUG, "file is not exit path:%s", file_path);
                send_down_filehead(sockfd, clientId, file_path, 0, FILE_NOT_EXIST);
            }
            free(file_path);
            file_path = NULL;
        }
        cJSON_Delete(pRank);
    }
}

//处理下载文件
void process_down_file(int sockfd, char *clientId, char *msg)
{
    cJSON *pRank = NULL, *pValue = NULL;
    pRank = cJSON_Parse(msg);
    if (pRank == NULL)
    {
        OUT_DEBUG(DEBUG, "json 解析异常");
        printf("msg:%s", msg);
    }
    else
    {
        pValue = cJSON_GetObjectItem(pRank, "filePath");
        if (pValue != NULL && pValue->type == cJSON_String)
        {
            int length = strlen(pValue->valuestring);
            char *file_path = charCopy(pValue->valuestring, length + 1);
            pValue = cJSON_GetObjectItem(pRank, "offset");
            int offset = 0;
            if (pValue != NULL && pValue->type == cJSON_Number)
            {
                offset = pValue->valueint;
            }
            if (isExist(file_path))
            {
                OUT_DEBUG(DEBUG, "file is exit");
                send_down_file(sockfd, clientId, file_path, offset);
            }
            else
            {
                OUT_DEBUG(DEBUG, "file is not exit");
            }
            free(file_path);
            file_path = NULL;
        }
        else
        {
            OUT_DEBUG(DEBUG, "filePath is not exit");
        }
        cJSON_Delete(pRank);
    }
}

//处理下载文件
void process_down_file_check(int sockfd, char *clientId, char *msg)
{
    cJSON *pRank = NULL, *pValue = NULL;
    pRank = cJSON_Parse(msg);
    if (pRank == NULL)
    {
        OUT_DEBUG(DEBUG, "json 解析异常");
        printf("msg:%s", msg);
    }
    else
    {
        pValue = cJSON_GetObjectItem(pRank, "resultCode");
        if (pValue != NULL && pValue->type == cJSON_Number)
        {
            int result_code = pValue->valueint;
            if (result_code < 1)
            {
                stop_tag_clientId = stringCopy(clientId, strlen(clientId));
            }
        }

        cJSON_Delete(pRank);
    }
}

void send_down_filehead(int sockfd, char *clientId, char *filename, long totalsize, int result_code)
{
    char data[1024];
    cJSON *down_check = NULL;
    cJSON *result_info = NULL;

    result_info = cJSON_CreateObject();
    cJSON_AddBoolToObject(result_info, "bResult", result_code);
    cJSON_AddNumberToObject(result_info, "resultCode", result_code);

    if (result_code == FILE_NOT_EXIST)
    {
        cJSON_AddStringToObject(result_info, "resultMsg", "file not exist");
    }
    else
    {
        cJSON_AddNumberToObject(result_info, "totalSize", totalsize);
        cJSON_AddStringToObject(result_info, "fileName", getfilename(filename));
    }

    down_check = cJSON_CreateObject();
    cJSON_AddStringToObject(down_check, "type", "DEVICE_FILE_DOWNLOAD_CHECK");
    cJSON_AddStringToObject(down_check, "clientId", get_routerid());
    cJSON_AddStringToObject(down_check, "content", cJSON_PrintUnformatted(result_info));
    if (clientId != NULL)
    {
        cJSON_AddStringToObject(down_check, "tagClientId", clientId);
    }

    char *buffer = cJSON_PrintUnformatted(down_check);
    int msg_size = strlen(buffer);
    memset(data, 0, sizeof(data));
    memcpy(data, buffer, msg_size);

    if (result_info != NULL)
    {
        cJSON_Delete(result_info);
    }
    if (down_check != NULL)
    {
        cJSON_Delete(down_check);
    }
    encode_msg(sockfd, data, msg_size);
}

void send_down_file(int sockfd, char *clientId, char *filepath, long offset)
{
    FileBody *file_body = (FileBody *)malloc(sizeof(FileBody));
    file_body->filePath = stringCopy(filepath, strlen(filepath));
    file_body->offset = offset;
    file_body->sockfd = sockfd;
    file_body->clientId = clientId;
    pthread_t psend;
    if (pthread_create(&psend, NULL, send_filebody, (void *)file_body) != 0)
    {
        OUT_DEBUG(DEBUG, "create_thread error");
    }
    pthread_join(psend, NULL);
}

void *send_filebody(void *args)
{
    FileBody *file_body = (FileBody *)args;
    int size = 0;
    FILE *fp = NULL;
    int p_size = 64 * 1024;
    long offset = file_body->offset;
    char buff[p_size];
    if ((fp = fopen(file_body->filePath, "rb")) == NULL)
    {
        printf("open file %s error, fp == NULL !\n", file_body->filePath);
        return NULL;
    }
    char *filename = getfilename(file_body->filePath);
    long totalsize = get_file_totalSize(file_body->filePath);
    fseek(fp, offset, SEEK_SET);
    while ((size = fread(buff, sizeof(char), p_size, fp)) != 0)
    {
        if (stop_tag_clientId != NULL)
        {
            if (!strcmp(stop_tag_clientId, file_body->clientId))
            {
                printf("clientId is stop !\n");
                free(stop_tag_clientId);
                stop_tag_clientId == NULL;
                break;
            }
        }
        FileInfo *file_info = create_file_info();
        file_info->filePath = stringCopy(file_body->filePath, strlen(file_body->filePath));
        file_info->fileName = stringCopy(filename, strlen(filename));
        file_info->totalsize = totalsize;
        file_info->currentIndex = offset;
        file_info->size = size;
        file_info->bytes = charCopy(buff, size);
        int ret = send_fileinfo(file_body->sockfd, file_body->clientId, file_info);
        if (ret == 0)
        {
            offset += size;
            if (file_info->bytes != NULL)
            {
                free(file_info->bytes);
                file_info->bytes = NULL;
            }
            freeFileInfo(file_info);
        }
        else if (ret == -1)
        {
            OUT_DEBUG(DEBUG, "can not send to some one:%d", file_body->sockfd);
            if (file_info->bytes != NULL)
            {
                free(file_info->bytes);
                file_info->bytes = NULL;
            }
            freeFileInfo(file_info);
            break;
        }
    }
    fclose(fp);
    free(filename);
    filename = NULL;
    return NULL;
}

//发送文件信息
int send_fileinfo(int sockfd, char *clientId, FileInfo *fileInfo)
{

    int ret = -1;
    cJSON *down_rsp = NULL;
    cJSON *down_content = NULL;
    down_content = cJSON_CreateObject();
    cJSON_AddStringToObject(down_content, "fileName", fileInfo->fileName);
    cJSON_AddNumberToObject(down_content, "size", fileInfo->size);
    cJSON_AddNumberToObject(down_content, "total", fileInfo->totalsize);
    cJSON_AddNumberToObject(down_content, "offset", fileInfo->currentIndex);

    down_rsp = cJSON_CreateObject();
    cJSON_AddStringToObject(down_rsp, "type", "DEVICE_FILE_DOWNLOAD_RSP");
    cJSON_AddStringToObject(down_rsp, "clientId", get_routerid());
    cJSON_AddStringToObject(down_rsp, "content", cJSON_PrintUnformatted(down_content));
    if (clientId != NULL)
    {
        cJSON_AddStringToObject(down_rsp, "tagClientId", clientId);
    }

    char *buffer = cJSON_PrintUnformatted(down_rsp);
    OUT_DEBUG(DEBUG, "buffer:%s", buffer);

    int msg_size = strlen(buffer);
    char *data = (char *)malloc(msg_size);
    memset(data, 0, sizeof(msg_size));
    memcpy(data, buffer, msg_size);

    cJSON_Delete(down_content);
    cJSON_Delete(down_rsp);

    int file_size = fileInfo->size;
    char *fbuffer = NULL;
    if (file_size > 0)
    {
        if (fileInfo->bytes != NULL)
        {
            fbuffer = (char *)malloc(file_size);
            if (fbuffer == NULL)
            {
                OUT_DEBUG(DEBUG, "FILE BYTES MALLOC ERROR,size:%d", file_size);
            }
            else
            {
                memset(fbuffer, 0, file_size);
                memcpy(fbuffer, fileInfo->bytes, file_size);
            }
        }
    }
    ret = encode_file_msg(sockfd, data, msg_size, fbuffer, file_size);
    free(data);
    data = NULL;
    free(buffer);
    buffer = NULL;
    if (fbuffer != NULL)
    {
        free(fbuffer);
        fbuffer = NULL;
    }
    return ret;
}